﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Data;
using OAuthLib;
using WTwitter.Model.Twitter;
using WTwitter.Model.UserData;
using System.ComponentModel;

namespace WTwitter.ViewModel {

	sealed public class OptionViewModel : ViewModelBase {

		#region private member
		private Option _option;
		private Consumer consumer = new Consumer(OAuthData.ConsumerKey, OAuthData.ConsumerSecret);
		private RequestToken reqToken;
		private string oAuthUserAuthorizationURL;
		private AccessToken accessToken;
		private List<TimelineSetting> _timelineSettingsBeforeEdit;
		#endregion

		#region Constructor
		public OptionViewModel(Option option) 
			: base("オプション設定") {
			_option = option;

			//タイムライン関係
			AddTimelineCommand = new RelayCommand(
				param => {
					var item = param as TimelineSettingTemplate;
					_option.AddTimeline(item);
				});
			RemoveTimelineCommand = new RelayCommand(
				param => _option.RemoveTimeline(param as TimelineSetting) );
			UpTimelineOrderCommand = new RelayCommand(
				param => _option.UpTimelineOrder(param as TimelineSetting) );
			DownTimelineOrderCommand = new RelayCommand(
				param => _option.DownTimelineOrder(param as TimelineSetting) );

			//認証情報関係
			ShowAuthInfoCommand = new RelayCommand(
					param => {
						try {
							var vm = new AccountInfoViewModel(_option.UserInfo);
							vm.GetInformation();
							Utility.ViewConnector.Instance.Show(vm);
						} catch {
						}
					}
				);

			//OAuth関係
			ShowOAuthURLCommand = new RelayCommand(
				param => {
					reqToken = consumer.ObtainUnauthorizedRequestToken(OAuthData.RequestTokenURL, OAuthData.AuthorizationRealm);
					oAuthUserAuthorizationURL = Consumer.BuildUserAuthorizationURL(OAuthData.AuthorizeURL, reqToken);
					this.OpenByBrowser(oAuthUserAuthorizationURL);}
				);
			GetAccessTokenCommand = new RelayCommand(
				param => {
					string verifier = param as string;
					accessToken = consumer.RequestAccessToken(verifier, reqToken, OAuthData.AccessTokenURL, OAuthData.AuthorizationRealm);
					_option.AccessTokenTmp = accessToken;
				}
			);
			ShowBitlyURLCommand = new RelayCommand(
				param => this.OpenByBrowser("http://bit.ly/"));
		}
		#endregion

		#region Command
		//タイムライン関係
		public RelayCommand AddTimelineCommand { get; private set; }
		public RelayCommand RemoveTimelineCommand { get; private set; }
		public RelayCommand UpTimelineOrderCommand { get; private set; }
		public RelayCommand DownTimelineOrderCommand { get; private set; }
		
		//OAuth関係
		public RelayCommand ShowOAuthURLCommand { get; private set; }
		public RelayCommand GetAccessTokenCommand { get; private set; }

		//認証情報関係
		public RelayCommand ShowAuthInfoCommand { get; private set; }

		//Bit.ly関係
		public RelayCommand ShowBitlyURLCommand { get; private set; }
		#endregion

		#region Property
		public AuthInfo UserInfo {
			get {
				return _option.UserInfo;
			}
		}

		public BitlySetting Bitly {
			get {
				return _option.Bitly;
			}
		}

		public ObservableCollection<TimelineSetting> TimelineSettings {
			get {
				return _option.TimelineSettings;
			}
		}

		private TimelineSettingTemplate[] _timelineSettingTemplates = new TimelineSettingTemplate[] {
			TimelineSettingTemplate.Home,
			TimelineSettingTemplate.Mentions,
			TimelineSettingTemplate.Friends,
			TimelineSettingTemplate.Favorites,
			TimelineSettingTemplate.Public,
			TimelineSettingTemplate.User,
			TimelineSettingTemplate.DirectMessage,
			TimelineSettingTemplate.DirectMessageSent,
			TimelineSettingTemplate.Search
		};

		public TimelineSettingTemplate[] TimelineSettingTemplates {
			get { return _timelineSettingTemplates; }
		}

		private string[] _skinList;
		public string[] Skins {
			get {
				if (_skinList == null) {
					var current = new System.IO.DirectoryInfo("skins");
					_skinList = current.GetDirectories().Select(folder => folder.Name).ToArray<string>();
				}
				return _skinList;
			}
		}

		public string Skin {
			get {
				return _option.Skin;
			}
			set {
				_option.Skin = value;
			}
		}

		#endregion

		#region BindingGroupの補完処理
		//BindingGroupのCancelEdit()でリストに追加した項目までは戻らないので、
		//BindingGroup相当の処理を同じタイミングで呼び出してリストを元に戻す処理をする
		//※もしかしたらちゃんとしたやりかたがあるのかもしれない

		public void CommitEdit() {
			for (int i = 0; i < _option.TimelineSettings.Count; i++) {
				_option.TimelineSettings[i].Index = i + 1;
			}
		}

		public void BeginEdit() {
			_timelineSettingsBeforeEdit = new List<TimelineSetting>(TimelineSettings);
		}

		public void CancelEdit() {
			if (TimelineSettings.SequenceEqual(_timelineSettingsBeforeEdit)) {
				return;
			}
			_option.TimelineSettings = new ObservableCollection<TimelineSetting>(_timelineSettingsBeforeEdit);
		}
		#endregion

		#region Public Method
		public void Save() {
			_option.Save();
		}
		#endregion

		#region private methos
		private void OpenByBrowser(string url) {
			Process.Start(url);
		}
		#endregion
	}
}
